home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / net / bind-contrib.tar.gz / bind-contrib.tar / contrib / misc / dnsrpt < prev    next >
Encoding:
Text File  |  1996-10-25  |  7.7 KB  |  303 lines

  1. #!/usr/local/bin/perl
  2. #
  3. # Copyright (c) 1993, 1994 by Silicon Systems Inc.
  4. # Permission to use, copy, modify, and distribute this software for any
  5. # purpose with or without fee is hereby granted, provided that this
  6. # copyright notice appear in all copies, and that the name of Silicon
  7. # Systems Inc. not be used in advertising or publicity pertaining to
  8. # distribution of the document or software without specific,
  9. # written prior permission.
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND SILICON SYSTEMS INC. DISCLAIMS ALL
  11. # WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  12. # OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL SILICON SYTEMS
  13. # INC. BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  15. # PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  16. # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  17. # SOFTWARE.
  18. #
  19. # Author: Don Lewis <gdonl@gv.ssi1.com>
  20. #
  21. # This perl script reads the /etc/named.boot file to find all the zone
  22. # files.  It reads the zone files and produces a report listing the
  23. # hosts sorted by both name and address in a format similar to that of
  24. # /etc/hosts (the difference being that this report contains multiple
  25. # address fields for multi-homed hosts).  This script checks that the
  26. # A RRs and PTR RRs match up, and also knows about CNAME RRs.
  27. #
  28. # This script is fairly dependent on having a complete set of the zone
  29. # files for a domain (both forward and reverse) accessable.
  30. #
  31. #  $Id: dnsrpt,v 8.2 1996/10/25 17:07:56 vixie Exp $
  32. #
  33.  
  34. sub getnonblank {
  35.     local ($line, $instring, $inparens, $saweof);
  36.     local ($handle) = @_;
  37.  
  38.     $instring = 0;
  39.     $inparens = 0;
  40.     $saweof = 0;
  41.  
  42.     do {
  43.     $line = '';
  44.     do {
  45.         $c = getc($handle);
  46.         if ($c eq ';') {
  47.         do {
  48.             $c = getc($handle);
  49.             if ($c eq '') {
  50.             last;
  51.             }
  52.         } while ($c ne "\n");
  53.         }
  54.         if ($c eq '') {
  55.         $saweof = 1;
  56.         last;
  57.         } elsif ($c eq ';') {
  58.         $line .= $c;
  59.         } else {
  60.         $line .= $c;
  61.         }
  62.         if ($instring) {
  63.         if ($c eq '"') {
  64.             $instring = 0;
  65.         }
  66.         } else {
  67.         if ($c eq '"') {
  68.             $instring = 1;
  69.         } elsif ($c eq '(') {
  70.             $inparens = 1;
  71.         } elsif ($c eq ')') {
  72.             $inparens = 0;
  73.         }
  74.         }
  75.     } while ( $inparens || $c ne "\n" );
  76.     } while ((! $saweof) && (split(/[ \t\n]/, $line) == 0));
  77.     return($line);
  78. }
  79.  
  80. sub parsezone {
  81.     local ($origin) = $_[0];
  82.     local ($zonefile) = $_[1];
  83.     local ($zonedata);
  84.     local ($owner, $lcowner);
  85.     local ($hostname, $lchostname);
  86.     
  87.     if ($origin ne '.') {
  88.     $origin .= '.';
  89.     }
  90.  
  91.     if ($directory ne '') {
  92.     $zonefile = $directory . '/' . $zonefile;
  93.     }
  94.  
  95.     if (! -f $zonefile) {
  96.     die "zone file '" . $zonefile . "' for zone '" . $origin .
  97.         "' is not a file\n";
  98.     }
  99.     if (open(zone, $zonefile) != 1) {
  100.     die "can't open zone file '" . $zonefile . "' for zone '" . $origin .
  101.         "'\n";
  102.     }
  103.  
  104.     while ($zonedata = &getnonblank(zone)) {
  105.     split(/[ \t\n]+/, $zonedata);
  106.     if ($_[0] eq '$ORIGIN') {
  107.         $origin = $_[1];
  108.     } else {
  109.         if ($_[0] ne '') {
  110.         if ($_[0] eq '@') {
  111.             $owner = $origin;
  112.         } elsif ($_[0] =~ /.*\.$/) {
  113.             $owner = $_[0];
  114.         } elsif ($origin eq '.') {
  115.             $owner = $_[0] . '.';
  116.         } else {
  117.             $owner = $_[0] . '.' . $origin;
  118.         }
  119.         }
  120.         ($lcowner = $owner) =~ y/A-Z/a-z/;
  121.         shift;      # skip owner
  122.         if ($_[0] =~ /^[0-9]+$/) {
  123.         shift;  # skip ttl
  124.         }
  125.         if ($_[0] ne 'IN') {
  126.         print "skipping non-IN class RR ", $zonedata;
  127.         next;
  128.         }
  129.         shift;      # skip class
  130.         if ($_[0] eq 'A') {
  131.         if ($addrtohost{$_[1]}) {
  132.             local (@tmpvar);
  133.             foreach $var (split(/ /, $addrtohost{$_[1]})) {
  134.             $tmpvar{$var} = 'junk';
  135.             }
  136.             if (! $tmpvar{$lcowner} ) {
  137.             $addrtohost{$_[1]} .= " " . $owner;
  138.             }
  139.         } else {
  140.             $addrtohost{$_[1]} = $owner;
  141.         }
  142.         if ($hosttoaddr{$lcowner}) {
  143.             local (@tmpvar);
  144.             foreach $var (split(/ /, $hosttoaddr{$lcowner})) {
  145.             $tmpvar{$var} = 'junk';
  146.             }
  147.             if (! $tmpvar{$_[1]} ) {
  148.             $hosttoaddr{$lcowner} .= " " . $_[1];
  149.             }
  150.         } else {
  151.             $hosttoaddr{$lcowner} = $_[1];
  152.         }
  153.         } elsif ($_[0] eq 'CNAME') {
  154.     
  155.         if ($_[1] =~ /.*\.$/) {
  156.             $hostname = $_[1];
  157.         } elsif ($origin eq '.') {
  158.             $hostname = $_[1] . '.';
  159.         } else {
  160.             $hostname = $_[1] . '.' . $origin;
  161.         }
  162.         ($lchostname = $hostname) =~ y/A-Z/a-z/;
  163.     
  164.         if ($hosttocname{$lchostname}) {
  165.             $hosttocname{$lchostname} .= " " . $owner;
  166.         } else {
  167.             $hosttocname{$lchostname} = $owner;
  168.         }
  169.         } elsif ($_[0] eq 'PTR') {
  170.         if ($ptrtohost{$lcowner}) {
  171.             $ptrtohost{$lcowner} .= " " . $_[1];
  172.         } else {
  173.             $ptrtohost{$lcowner} = $_[1];
  174.         }
  175.         }
  176.     }
  177.     }
  178.  
  179.     close(zone);
  180. }
  181.  
  182. sub cmpaddr {
  183.     local (@addr1) = split(/\./, $a);
  184.     local (@addr2) = split(/\./, $b);
  185.  
  186.     for ($i = 0; $i < 4; $i++) {
  187.     if ($addr1[$i] != $addr2[$i]) {
  188.         return($addr1[$i] - $addr2[$i]);
  189.     }
  190.     }
  191.     return(0);
  192. }
  193.  
  194. if (open(bootfile, "</etc/named.boot") != 1) {
  195.     die "can't open /etc/named.boot\n";
  196. }
  197.  
  198. while ($cmd = &getnonblank(bootfile)) {
  199.     split(/[ \t\n]+/, $cmd);
  200.     if ($_[0] eq 'directory') {
  201.     $directory = $_[1];
  202.     } elsif ($_[0] eq 'primary') {
  203.     &parsezone( $_[1], $_[2]);
  204.     } elsif ($_[0] eq 'secondary') {
  205.     &parsezone( $_[1], $_[$#_]);
  206.     }
  207. }
  208.  
  209. foreach $addr (keys(%addrtohost)) {
  210.     $ptr = $ptrtohost{ join('.', reverse(split(/\./, $addr))) .
  211.     '.in-addr.arpa.' };
  212.     ($lcptr = $ptr) =~ y/A-Z/a-z/;
  213.     $hostname = $addrtohost{$addr};
  214.     @hostname = split(/ /, $hostname);
  215.     ($lchostname = $hostname) =~ y/A-Z/a-z/;
  216.     @lchostname = split(/ /, $lchostname);
  217.     @unmatched = ();
  218.  
  219.     if (! $ptr ) {
  220.     print "address ", $addr,
  221.         " (", $hostname, ") has no matching PTR record\n";
  222.     } else {
  223.     foreach (@lchostname) {
  224.         if ( $lcptr ne $_ ) {
  225.         push( @unmatched, shift( @hostname ) );
  226.         }
  227.     }
  228.     if ( $#lchostname == $#unmatched ) {
  229.         print "address ", $addr, " has name ", $hostname, " and PTR ",
  230.         $ptr, "\n";
  231.     } elsif ( $#unmatched > 1 ) {
  232.         print "address ", $addr, " has extra names ",
  233.         join(' ', @unmatched), "\n";
  234.     } elsif ( $#unmatched > 0 ) {
  235.         print "address ", $addr, " has extra name ", $unmatched[0], "\n";
  236.     }
  237.     }
  238. }
  239.  
  240. foreach $ptr (keys(%ptrtohost)) {
  241.     $hostname = $ptrtohost{$ptr};
  242.     ($lchostname = $hostname) =~ y/A-Z/a-z/;
  243.     @parts = split(/\./, $ptr);
  244.  
  245.     if ($parts[$#parts] =~ /^arpa$/i && $parts[$#parts - 1] =~ /^in-addr$/i) {
  246.  
  247.     if ( ! $hosttoaddr{$lchostname} ) {
  248.         if ( $ptrtohost{$lchostname} ) {
  249.         if ( $ptrtohost{$lchostname} ne $ptr ) {
  250.             print "mismatched PTRs for ", $ptr, " and ", $hostname,
  251.             "\n";
  252.         }
  253.         } else {
  254.         print "PTR ", $ptr, " refers to unknown host ", $hostname, "\n";
  255.         }
  256.     } else {
  257.         $addr = $parts[3] . '.' . $parts[2] . '.' . $parts[1] .
  258.         '.' . $parts[0];
  259.  
  260.         if ( ! $addrtohost{$addr} ) {
  261.         print "PTR ", $ptr, " to ", $hostname,
  262.             " has an invalid address\n";
  263.         } elsif ( $hostname ne $addrtohost{$addr} ) {
  264. # duplicate warning
  265. #        print "PTR ", $ptr, " to ", $hostname, " has address of host ",
  266. #            $addrtohost{$addr}, "\n";
  267.         }
  268.     }
  269.     } elsif ( ! $ptrtohost{$lchostname} ) {
  270.     print "network PTR ", $ptr, " to ", $hostname, " is dangling\n";
  271.     }
  272. }
  273.  
  274. print "                        Hosts Sorted by Name\n\n\n";
  275.  
  276. foreach $host (sort(keys(%hosttoaddr))) {
  277.     $count = 0;
  278.     foreach $addr (split(/ /, $hosttoaddr{$host})) {
  279.     $count++;
  280.     printf("%-16s", $addr);
  281.     }
  282.     for (; $count < 2; $count++) {
  283.     printf("%-16s", "");
  284.     }
  285.     printf "  %s", $host;
  286.     if ($hosttocname{$host}) {
  287.     print ' ', $hosttocname{$host};
  288.     }
  289.     print "\n";
  290. }
  291.  
  292. print "\f                        Hosts Sorted by Address\n\n\n";
  293.  
  294. foreach $addr (sort(cmpaddr keys(%addrtohost))) {
  295.     printf "%-32s  %s", $addr, $addrtohost{$addr};
  296.     if ($hosttocname{$addrtohost{$addr}}) {
  297.     print ' ', $hosttocname{$addrtohost{$addr}};
  298.     }
  299.     print "\n";
  300. }
  301.